package model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

/**
 * 
 * @author Søren
 * 
 */
@Entity
public class Lager {
	@OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
	@JoinColumn
	private List<LagerPlads> lagerpladser;
	@Id
	@GeneratedValue
	private int id;
	
	@OneToOne
	@JoinColumn(nullable = false)
	private static Lager uniqueInstance;
	
	private long senesteVareNr = 0;

	private Lager(int antalPladser) {
		this.lagerpladser = new ArrayList<LagerPlads>();

		for (int i = 0; i < antalPladser; i++) {
			lagerpladser.add(new LagerPlads(i + 1));
		}
	}

	public Lager() {

	}

	/**
	 * Sikrer, at der kun eksisterer et enkelt lager på et hvert givent
	 * tidspunkt
	 * 
	 * @return returnerer det eksisterende lager.
	 */
	public static Lager getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Lager(48);
		}
		return uniqueInstance;
	}

	public LagerPlads getFriPlads() {
		for (LagerPlads lp : lagerpladser) {
			if (lp.getMellemVare() == null) {
				return lp; // Returnerer den første frie lagerplads
			}
		}
		return null; // Returnerer null hvis ingen lagerpladser er frie
	}

	/**
	 * Returnerer det næste varenr.
	 * 
	 * @return det næste varenr.
	 */
	public long getNaesteVareNr() {
		senesteVareNr++;
		return senesteVareNr;
	}

	/**
	 * Bruges til at flytte en mellemvare fra en lagerplads til en anden.
	 * 
	 * @param fra
	 *            Nummeret på den lagerplads, der skal flyttes fra.
	 * @param til
	 *            Nummeret på den lagerplads, der skal flyttes til.
	 */
	public void flytMellemvare(int fra, int til) {
		LagerPlads fraPlads = null, tilPlads = null;
		for (LagerPlads lp : lagerpladser) {
			if (lp.getPladsNr() == fra) {
				fraPlads = lp;
			} else if (lp.getPladsNr() == til) {
				if (lp.getMellemVare() == null) {
					tilPlads = lp;
				} else {
					throw new RuntimeException(
							"Destinationslagerpladsen er ikke tom!");
				}
			}
		}

		if (fraPlads != null && tilPlads != null) {
			if (!fraPlads.equals(tilPlads)) {

				tilPlads.setMellemVare(fraPlads.getMellemVare());
				fraPlads.setMellemVare(null);
			} else {
				throw new RuntimeException(
						"Du kan ikke flytte en vare til dens egen plads.");
			}
		} else {
			throw new RuntimeException(
					"En af de ønskede pladser blev ikke fundet");

		}
	}

	/**
	 * Fjerner en mellemvare fra mellemvarelageret.
	 * 
	 * @param m
	 *            Den mellemvare, der skal fjernes.
	 */
	public void fjernMellemvare(MellemVare m) {
		for (LagerPlads lp : lagerpladser) {
			if (lp.getMellemVare() == m) {
				lp.setMellemVare(null);
			}
		}
	}

	public int getAntalPladser() {
		return lagerpladser.size();
	}

	public List<LagerPlads> getLagerPladser() {
		return lagerpladser;
	}

	/**
	 * Søger lageret igennem for at finde en given mellemvares placering.
	 * 
	 * @param m
	 *            Den mellemvare, der bliver søgt efter.
	 * @return Den lagerplads, mellemvaren står på. NULL hvis mellemvare ikke
	 *         blev fundet på lageret.
	 */
	public LagerPlads findMellemVare(MellemVare m) {
		for (LagerPlads lp : lagerpladser) {
			if (lp.getMellemVare() == m) {
				return lp;
			}
		}
		return null;
	}

}
